/*
  Copyright (C) 2013 Napspirit / Thierry Rochelet

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.napspirit.tmx.ui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

import javax.swing.filechooser.FileNameExtensionFilter;

import com.napspirit.tmx.data.*;
import com.napspirit.tmx.NapTMX;


public class Frame extends JFrame 
    implements ActionListener , TMXListener {

    // Menu bar
    private JMenuBar menuBar;

    // open a file
    private JMenuItem openItem;
    // close a file
    private JMenuItem closeItem;
    // create a new file
    private JMenuItem newItem;
    // save current file
    private JMenuItem saveItem;
    // save current file
    private JMenuItem saveAsItem;
    // quit application
    private JMenuItem quitItem;

    // new category
    private JMenuItem newTUCategory;
    // new TU
    private JMenuItem newTUItem;
    // save TU
    private JMenuItem saveTUItem;
    // delete
    private JMenuItem deleteTUItem;
    // new TUV
    private JMenuItem newTUVItem;

    // Tool
    private JMenuItem import1Item;
    private JMenuItem import2Item;


    // About
    private JMenuItem aboutItem;
    private JMenuItem licenceItem;

    // current status
    // -1 : starting
    // 0 : no file open
    // 1 : file open (with no changes)
    // 2 : file open (with changes)
    // 3 : new file  (with or without changes !)
    private int status;

    // Current TMX stuff !!
    private TMX tmx;
    
    private TMXTUPanel tuPanel;
    private ListPanel listPanel;
    private JSplitPane splitPane;

    private JFileChooser fileChooser;

    private String name;

    public Frame(String name) {
        super(name);
        this.name = name;

        this.status = -1; // no status
        this.tmx = new TMX();
        this.tmx.addListener(this);

        this.fileChooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("TMX files", "tmx", "xml");
        this.fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        this.fileChooser.setFileFilter(filter);

        // menu bar
        this.init_menubar();
        this.setJMenuBar(this.menuBar);

        this.listPanel = new ListPanel(this);
        this.listPanel.setPreferredSize(new Dimension(250,500));

        this.tuPanel = new TMXTUPanel(this);
        this.tuPanel.setPreferredSize(new Dimension(400,500));

        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);


        //Create a split pane with the two scroll panes in it.
        this.splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,this.listPanel,this.tuPanel);
        this.splitPane.setOneTouchExpandable(true);
        this.splitPane.setDividerLocation(230);

        this.setLayout(new BorderLayout());
        this.add(this.splitPane, BorderLayout.CENTER);
        this.setResizable(true);

        // Be sure we can close the application !:!
        this.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we) {
                    if (confirmClose()) { System.exit(0);  }
                }
            });
        
        this.set_status(0);
    }

    public TMX getTMX () { return this.tmx; }

    /**
     * Set the status... only prepare the menu...no process
     *
     * @param nstatus an <code>int</code> value
     */
    private final void set_status (int nstatus) {
        if (this.status == nstatus) {
            return;
        }
        
        switch (nstatus) {
            
        case 0: { // no file open
            this.newItem.setEnabled(true);
            this.openItem.setEnabled(true);

            this.closeItem.setEnabled(false);
            this.saveItem.setEnabled(false);
            this.saveAsItem.setEnabled(false);

            this.newTUCategory.setEnabled(false);
            this.newTUItem.setEnabled(false);

            this.import1Item.setEnabled(false);
            this.import2Item.setEnabled(false);
        }
            break;

        case 1: { // file open (with no changes)
            this.newItem.setEnabled(false);
            this.openItem.setEnabled(false);

            this.closeItem.setEnabled(true);
            this.saveItem.setEnabled(false);
            this.saveAsItem.setEnabled(false);

            this.newTUCategory.setEnabled(true);
            this.newTUItem.setEnabled(true);

            this.import1Item.setEnabled(true);
            this.import2Item.setEnabled(true);
        }
            break;

        case 2: { // file open (with changes)
            this.newItem.setEnabled(false);
            this.openItem.setEnabled(false);

            this.closeItem.setEnabled(true);
            this.saveItem.setEnabled(true);
            this.saveAsItem.setEnabled(true);

            this.newTUCategory.setEnabled(true);
            this.newTUItem.setEnabled(true);

            this.import1Item.setEnabled(true);
            this.import2Item.setEnabled(true);
        }
            break;

        case 3: { // new file  (with or without changes !)
            this.newItem.setEnabled(false);
            this.openItem.setEnabled(false);

            this.closeItem.setEnabled(true);
            this.saveItem.setEnabled(false);
            this.saveAsItem.setEnabled(true);

            this.newTUCategory.setEnabled(true);
            this.newTUItem.setEnabled(true);

            this.import1Item.setEnabled(true);
            this.import2Item.setEnabled(true);
        }
            break;


        default:
            break;
        }

        this.status = nstatus;
    }


    private final void init_menubar() {
        this.menuBar = new JMenuBar();

        // ===== FILE =====
        JMenu fileMenu = new JMenu("File");

        this.newItem = new JMenuItem("New TMX file");
        this.newItem.addActionListener(this);
        fileMenu.add(this.newItem);

        this.openItem = new JMenuItem("Open a TMX file");
        this.openItem.addActionListener(this);
        fileMenu.add(this.openItem);

        fileMenu.addSeparator();

        this.closeItem = new JMenuItem("Close current file");
        this.closeItem.addActionListener(this);
        fileMenu.add(this.closeItem);

        this.saveItem = new JMenuItem("Save current file");
        this.saveItem.addActionListener(this);
        fileMenu.add(this.saveItem);

        this.saveAsItem = new JMenuItem("Save current file as...");
        this.saveAsItem.addActionListener(this);
        fileMenu.add(this.saveAsItem);


        fileMenu.addSeparator();

        this.quitItem = new JMenuItem("Quit");
        this.quitItem.addActionListener(this);
        fileMenu.add(this.quitItem);

        this.menuBar.add(fileMenu);


        // ===== Current TU =====
        JMenu tuMenu = new JMenu("Translation unit");

        this.newTUCategory = new JMenuItem("New category");
        this.newTUCategory.addActionListener(this);
        tuMenu.add(this.newTUCategory);

        this.newTUItem = new JMenuItem("New TU");
        this.newTUItem.addActionListener(this);
        tuMenu.add(this.newTUItem);
        

        this.deleteTUItem = new JMenuItem("Delete TU");
        this.deleteTUItem.addActionListener(this);
        tuMenu.add(this.deleteTUItem);
        
        tuMenu.addSeparator();

        this.newTUVItem = new JMenuItem("New language");
        this.newTUVItem.addActionListener(this);
        tuMenu.add(this.newTUVItem);

        this.menuBar.add(tuMenu);

        // ===== Tools =====

        JMenu toolsMenu = new JMenu("Tools");

        this.import1Item = new JMenuItem("Import new TUV");
        this.import1Item.addActionListener(this);
        toolsMenu.add(this.import1Item);

        this.import2Item = new JMenuItem("Import new TU and TUV");
        this.import2Item.addActionListener(this);
        toolsMenu.add(this.import2Item);

        this.menuBar.add(toolsMenu);

        // ===== SAVE TU =====
        this.menuBar.add(Box.createHorizontalGlue());
        this.saveTUItem = new JMenuItem("Save TU");
        this.saveTUItem.addActionListener(this);
        this.saveTUItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
        this.saveTUItem.setEnabled(false);
        this.menuBar.add(this.saveTUItem);


        // ==== Go to right ====
        this.menuBar.add(Box.createHorizontalGlue());


        // ===== About =====

        JMenu aboutMenu = new JMenu("About");

        this.aboutItem = new JMenuItem("About "+NapTMX.APPLICATION_NAME);
        this.aboutItem.addActionListener(this);
        aboutMenu.add(this.aboutItem);

        this.licenceItem = new JMenuItem("Licence");
        this.licenceItem.addActionListener(this);
        aboutMenu.add(this.licenceItem);

        this.menuBar.add(aboutMenu);
        
    }

    
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == this.openItem) {
            int res = this.fileChooser.showOpenDialog(this);
            if (res == JFileChooser.APPROVE_OPTION) {
                try {
                    File tmp = this.fileChooser.getSelectedFile();
                    this.tmx.load(tmp.getAbsolutePath());
                    this.setTitle(this.name + " - " + this.tmx.getTitle());
                    this.set_status(1);
                    this.refresh();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        else if (event.getSource() == this.saveItem) {
            if (confirmChangeCurrent()) {
                try {
                    this.tmx.save();
                    this.setTitle(this.name + " - " + this.tmx.getTitle());
                    this.set_status(1);
                    this.refresh();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } 
        else if (event.getSource() == this.saveAsItem) {
            if (confirmChangeCurrent()) {
                int res = this.fileChooser.showSaveDialog(this);
                if (res == JFileChooser.APPROVE_OPTION) {
                    try {
                        File tmp = this.fileChooser.getSelectedFile();
                        this.tmx.save(tmp.getAbsolutePath());
                        this.setTitle(this.name + " - " + this.tmx.getTitle());
                        this.set_status(1);
                        this.refresh();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } 
        else if (event.getSource() == this.newItem) {
            if (confirmClose()) {
                this.tmx.init();
                this.set_status(3);
                this.refresh();
            }
        }
        else if (event.getSource() == this.closeItem) {
            if (confirmClose()) {
                this.tmx.init();
                this.set_status(0);
                this.refresh();
            }
        }
        else if (event.getSource() == this.newTUCategory) {
            if (this.confirmChangeCurrent()) {
                String res = (String)JOptionPane.showInputDialog(this,"New cateogry","Category",JOptionPane.QUESTION_MESSAGE,null,null,null);
                if (res!=null) {
                    this.tmx.registerCategory(res);
                    this.refreshEntry();
                }
            }
        }
        else if (event.getSource() == this.newTUItem) {
            if (this.confirmChangeCurrent()) {
                this.tmx.createTU();                
            }
        }
        else if (event.getSource() == this.newTUVItem) {
            TMXTU tu = this.tmx.getCurrent();
            if (tu!=null) {
                String [] langs = tu.getNotDefinedLocales();
                String res = (String)JOptionPane.showInputDialog(this,"Choose a language","Language",JOptionPane.QUESTION_MESSAGE,null,langs,langs[0]);
                if (res!=null) {
                    Locale locale = new Locale(res);
                    tu.registerLocale(locale);
                    this.refreshEntry();
                }
            }

        }
        else if (event.getSource() == this.deleteTUItem) {
            int res = JOptionPane.showConfirmDialog(this,"Are you sure you want to delete this entry ?","Confirm", JOptionPane.YES_NO_OPTION);
            if (res == JOptionPane.YES_OPTION) {
                this.tmx.deleteTU(this.tmx.getCurrent());
            }
        }
        else if (event.getSource() == this.saveTUItem) {
            this.tuPanel.save();
        }

        // ==== IMPORT ====
        else if (event.getSource() == this.import1Item) {
            int res = this.fileChooser.showOpenDialog(this);
            if (res == JFileChooser.APPROVE_OPTION) {
                try {
                    File tmp = this.fileChooser.getSelectedFile();
                    TMX importTMX = new TMX();
                    importTMX.load(tmp.getAbsolutePath());

                    boolean test = this.confirmRunTest();
                    String report = this.tmx.importFrom(1,test,importTMX);

                    ReportDialog rd = new ReportDialog(report);
                    rd.setVisible(true);            
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } 

        else if (event.getSource() == this.import2Item) {
            int res = this.fileChooser.showOpenDialog(this);
            if (res == JFileChooser.APPROVE_OPTION) {
                try {
                    File tmp = this.fileChooser.getSelectedFile();
                    TMX importTMX = new TMX();
                    importTMX.load(tmp.getAbsolutePath());

                    boolean test = this.confirmRunTest();
                    String report = this.tmx.importFrom(2,test,importTMX);

                    ReportDialog rd = new ReportDialog(report);
                    rd.setVisible(true);            

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } 


        // ==== ABOUT ====
        else if (event.getSource() == this.aboutItem) {
            AboutDialog ad = new AboutDialog();
            ad.setVisible(true);            
        } 

        else if (event.getSource() == this.licenceItem) {
            LicenceDialog ld = new LicenceDialog();
            ld.setVisible(true);            
        } 


        // ==== QUIT ====
        else if (event.getSource() == this.quitItem) {
            if (confirmClose()) { System.exit(0); }
        } 
    }

    /** returns true : means we want to run it as a test */
    public boolean confirmRunTest () {
        Object[] options = {"Run as a test",
                            "Run it !"};
        int res = JOptionPane.showOptionDialog(this,"Do you want to run or to test it ?","Test/Run",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,null,options,options[0]);
        if (res == 0) {
            return true;
        } else {
            return false;
        }                        
    }


    public boolean confirmChangeCurrent () {
        if (this.tuPanel.isModified()) {
            int res = JOptionPane.showConfirmDialog(this,"Current edit translation unid is not saved ... continue ?","Confirm", JOptionPane.YES_NO_OPTION);
            if (res == JOptionPane.YES_OPTION) {
                return true;
            } else {
                return false;
            }                        
        }
        return true;
    }

    /** Confirm to close (and loose changes) */
    public boolean confirmClose() {
        if (!this.confirmChangeCurrent()) {
            return false;
        }

        if (this.status==2) {
            int res = JOptionPane.showConfirmDialog(this,"Current file was modifier. Do you wan't to loose changes ?","Confirm", JOptionPane.YES_NO_OPTION);
            if (res == JOptionPane.YES_OPTION) {
                return true;
            } else {
                return false;
            }            
        }
        else if (this.status==3) {
            int res = JOptionPane.showConfirmDialog(this,"New file was modified. Do you wan't to loose changes ?","Confirm", JOptionPane.YES_NO_OPTION);
            if (res == JOptionPane.YES_OPTION) {
                return true;
            } else {
                return false;
            }            
        }
        return true;
    }


    public void TMXModified () {
        if (this.status==1) {
            this.set_status(2);
        }
        this.refresh();
    }
    

    // =============== currently edited yu ==================

    public void current_tu_empty () {
        this.newTUCategory.setEnabled(true);
        this.newTUItem.setEnabled(true);
        this.newTUVItem.setEnabled(false);
        this.saveTUItem.setEnabled(false);
        this.deleteTUItem.setEnabled(false);        
    }

    /** Current TMXTU modified */
    public void current_tu_modified () {
        this.newTUCategory.setEnabled(false);
        this.newTUItem.setEnabled(false);
        this.newTUVItem.setEnabled(true);
        this.saveTUItem.setEnabled(true);        
        this.deleteTUItem.setEnabled(true);        
    }

    /** Current TMXTUdisplayed (nut not modified) */
    public void current_tu_displayed () {
        this.newTUCategory.setEnabled(true);
        this.newTUItem.setEnabled(true);
        this.newTUVItem.setEnabled(true);
        this.saveTUItem.setEnabled(false);
        this.deleteTUItem.setEnabled(true);
    }


    // =============== Panel ==================

    public void refresh() { 
        this.listPanel.refresh();
        this.tuPanel.refresh(); 
    }

    public void refreshList() { 
        this.listPanel.refresh();
    }

    public void refreshEntry() { 
        this.tuPanel.refresh();
    }


}
